home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP07.ZIP / CHAP07 / PATRON / TENANT.CPP < prev   
C/C++ Source or Header  |  1993-06-07  |  22KB  |  940 lines

  1. /*
  2.  * TENANT.CPP
  3.  * Addition for Chapter 7
  4.  *
  5.  * Implementation of the CTentant class which holds information
  6.  * for a single object on a page.  It maintains position, references
  7.  * to data, and a storage.
  8.  *
  9.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Software Design Engineer
  12.  * Microsoft Systems Developer Relations
  13.  *
  14.  * Internet  :  kraigb@microsoft.com
  15.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  16.  */
  17.  
  18.  
  19. #include "patron.h"
  20.  
  21.  
  22. /*
  23.  * CTenant::CTenant
  24.  * CTenant::~CTenant
  25.  *
  26.  * Constructor Parameters:
  27.  *  dwID            DWORD identifier for this page.
  28.  *  hWnd            HWND of the pages window.
  29.  *  pPG             LPCPages to the parent structure.
  30.  */
  31.  
  32. CTenant::CTenant(DWORD dwID, HWND hWnd, LPCPages pPG)
  33.     {
  34.     m_hWnd=hWnd;
  35.     m_dwID=dwID;
  36.  
  37.     m_fInitialized=0;
  38.     m_pIStorage=NULL;
  39.     m_cOpens=0;
  40.  
  41.     m_pObj=NULL;
  42.     m_pPG =pPG;
  43.     return;
  44.     }
  45.  
  46.  
  47. CTenant::~CTenant(void)
  48.     {
  49.    #ifdef DEBUG
  50.     char    szTemp[128];
  51.     if (0!=m_cOpens)
  52.         {
  53.         wsprintf(szTemp, "::~CTenant m_cOpens=%lu", m_cOpens);
  54.         MessageBox(m_hWnd, szTemp, "Assert", MB_OK);
  55.         }
  56.    #endif
  57.  
  58.     if (NULL!=m_pObj)
  59.         {
  60.         //We know we only hold one reference from UCreate or FLoad
  61.         m_pObj->Release();
  62.         m_pObj=NULL;
  63.         }
  64.  
  65.     return;
  66.     }
  67.  
  68.  
  69.  
  70. /*
  71.  * CTenant::GetID
  72.  *
  73.  * Return Value:
  74.  *  DWORD           dwID field in this tenant.  This function is only here
  75.  *                  to avoid hiding inline implementations in pages.h
  76.  */
  77.  
  78. DWORD CTenant::GetID(void)
  79.     {
  80.     return m_dwID;
  81.     }
  82.  
  83.  
  84.  
  85. /*
  86.  * CTenant::GetStorageName
  87.  *
  88.  * Parameters:
  89.  *  pszName         LPSTR to a buffer in which to store the storage name
  90.  *                  for this tenant.
  91.  *
  92.  * Return Value:
  93.  *  UINT            Number of characters stored.
  94.  */
  95.  
  96. UINT CTenant::GetStorageName(LPSTR pszName)
  97.     {
  98.     return wsprintf(pszName, "Tenant %lu", m_dwID);
  99.     }
  100.  
  101.  
  102.  
  103.  
  104.  
  105. /*
  106.  * CTenant::UCreate
  107.  *
  108.  * Purpose:
  109.  *  Creates a new tenant of the given CLSID, which can be either a
  110.  *  static bitmap or metafile now (Chapter 7) and which may eventually
  111.  *  be any OLE object.
  112.  *
  113.  * Parameters:
  114.  *  tType           TENANTTYPE to create, either a static metafile, bitmap,
  115.  *                  or some kind of OLE object (later chapters)
  116.  *                  This determined which OleCreate* call we use.
  117.  *  pvType          LPVOID providing the relevant pointer from which
  118.  *                  to create the tenant, depending on iType.
  119.  *  pFE             LPFORMATETC specifying the type of renderings to use.
  120.  *  pptl            LPPOINTL in which we can store offset coordinates.
  121.  *  pszl            LPSIZEL where this object should store its lometric extents.
  122.  *  pIStorage       LPSTORAGE of the page we live in.  We have to
  123.  *                  create another storage under this for the tenant.
  124.  *  ppo             LPPATRONOBJECT containing placement data.
  125.  *  dwData          DWORD containing extra data, sensitive to iType.
  126.  *
  127.  * Return Value:
  128.  *  UINT            A UCREATE_* value depending on what we actually do.
  129.  */
  130.  
  131. UINT CTenant::UCreate(TENANTTYPE tType, LPVOID pvType, LPFORMATETC pFE
  132.     , LPPOINTL pptl, LPSIZEL pszl, LPSTORAGE pIStorage
  133.     , LPPATRONOBJECT ppo, DWORD dwData)
  134.     {
  135.     HRESULT         hr;
  136.     LPUNKNOWN       pObj;
  137.     LPOLEOBJECT     pIOleObject;
  138.     UINT            uRet=UCREATE_GRAPHICONLY;
  139.  
  140.     if (NULL==pvType || NULL==pIStorage)
  141.         return UCREATE_FAILED;
  142.  
  143.     //Fail if this is called for an already living tenant.
  144.     if (m_fInitialized)
  145.         return UCREATE_FAILED;
  146.  
  147.     m_fInitialized=TRUE;
  148.  
  149.     //Create a new storage for this tenant.
  150.     if (!FOpen(pIStorage))
  151.         return UCREATE_FAILED;
  152.  
  153.     /*
  154.      * Get the placement info if it's here.  We either have a non-NULL
  155.      * LPPATRONOBJECT in ppo or we have to use default placement and
  156.      * retrieve the size from the object itself.
  157.      */
  158.     pszl->cx=0;
  159.     pszl->cy=0;
  160.  
  161.     if (NULL!=ppo)
  162.         {
  163.         *pFE=ppo->fe;
  164.         *pptl=ppo->ptl;
  165.         *pszl=ppo->szl;     //Could be 0,0 in which case we ask object
  166.  
  167.         uRet=UCREATE_PLACEDOBJECT;
  168.         }
  169.  
  170.     hr=ResultFromScode(E_FAIL);
  171.  
  172.     //Now create an object based specifically for the type.
  173.     switch (tType)
  174.         {
  175.         case TENANTTYPE_NULL:
  176.             break;
  177.  
  178.         case TENANTTYPE_STATIC:
  179.             /*
  180.              * We could use OleCreateStaticFromData here which does
  181.              * pretty much what we're doing below.  However, it does
  182.              * not allow us to control whether we paste a bitmap or
  183.              * a metafile--it uses metafile first, bitmap second.  For
  184.              * this reason we'll use code developed in Chapter 6's
  185.              * FreeLoader to affect the paste.
  186.              */
  187.             hr=CreateStatic((LPDATAOBJECT)pvType, pFE, &pObj);
  188.             break;
  189.  
  190.         default:
  191.             break;
  192.         }
  193.  
  194.     //If creation didn't work, get rid for the element FOpen created.
  195.     if (FAILED(hr))
  196.         {
  197.         Destroy(pIStorage);
  198.         return UCREATE_FAILED;
  199.         }
  200.  
  201.     //Otherwise, store the object pointer and initialize the tenant
  202.     m_pObj=pObj;
  203.     m_fe=*pFE;
  204.     m_dwState=TENANTSTATE_DEFAULT;
  205.  
  206.     //If we also saw PatronObjects on the clipboard, we have size already.
  207.  
  208.     if (0==pszl->cx && 0==pszl->cy)
  209.         {
  210.         //Try to get the real size of the object, default to 2"*2"
  211.         SETSIZEL((*pszl), 2*LOMETRIC_PER_INCH, 2*LOMETRIC_PER_INCH);
  212.         hr=pObj->QueryInterface(IID_IOleObject, (LPVOID FAR *)&pIOleObject);
  213.  
  214.         if (SUCCEEDED(hr))
  215.             {
  216.             SIZEL   szl;
  217.  
  218.             pIOleObject->GetExtent(pFE->dwAspect, &szl);
  219.             pIOleObject->Release();
  220.  
  221.             //Convert HIMETRIC to our LOMETRIC mapping
  222.             SETSIZEL((*pszl), szl.cx/10, szl.cy/10);
  223.             }
  224.         }
  225.  
  226.     return uRet;
  227.     }
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234. /*
  235.  * CTenant::FLoad
  236.  *
  237.  * Purpose:
  238.  *  Recreates the object living in this tenant in place of calling
  239.  *  FCreate.  This is used in loading as opposed to new creation.
  240.  *
  241.  * Parameters:
  242.  *  pIStorage       LPSTORAGE of the page we live in.
  243.  *  pFE             LPFORMATETC specifying the type of renderings to use.
  244.  *  prcl            LPRECTL where this object is positioned.
  245.  *
  246.  * Return Value:
  247.  *  BOOL            TRUE if successful, FALSE otherwise.
  248.  */
  249.  
  250. BOOL CTenant::FLoad(LPSTORAGE pIStorage, LPFORMATETC pFE, LPRECTL prcl)
  251.     {
  252.     HRESULT         hr;
  253.     LPUNKNOWN       pObj;
  254.  
  255.     if (NULL==pIStorage || NULL==pFE || NULL==prcl)
  256.         return FALSE;
  257.  
  258.     //Fail if this is called for an already living tenant.
  259.     if (m_fInitialized)
  260.         return FALSE;
  261.  
  262.     m_fInitialized=TRUE;
  263.  
  264.     //Open the storage for this tenant.
  265.     if (!FOpen(pIStorage))
  266.         return FALSE;
  267.  
  268.     hr=OleLoad(m_pIStorage, IID_IUnknown, NULL, (LPVOID FAR *)&pObj);
  269.  
  270.     if (FAILED(hr))
  271.         {
  272.         Destroy(pIStorage);
  273.         return FALSE;
  274.         }
  275.  
  276.     //Otherwise, store the object pointer and initialize the tenant
  277.     m_pObj=pObj;
  278.     m_fe=*pFE;
  279.     m_dwState=TENANTSTATE_DEFAULT;
  280.  
  281.     RectSet(prcl, FALSE);
  282.     return TRUE;
  283.     }
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292. /*
  293.  * CTenant::FOpen
  294.  *
  295.  * Purpose:
  296.  *  Retrieves the IStorage associated with this tenant.  The IStorage is
  297.  *  owned by the tenant and thus the tenant always holds a reference count.
  298.  *
  299.  *  If the storage is already open for this tenant, then this function will
  300.  *  AddRef it; therefore the caller must always match an FOpen with a Close.
  301.  *
  302.  * Parameters:
  303.  *  pIStorage       LPSTORAGE above this tenant (which has its own storage).
  304.  *
  305.  * Return Value:
  306.  *  BOOL            TRUE if opening succeeds, FALSE otherwise.
  307.  */
  308.  
  309. BOOL CTenant::FOpen(LPSTORAGE pIStorage)
  310.     {
  311.     HRESULT     hr=NOERROR;
  312.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  313.     char        szTemp[32];
  314.  
  315.     if (NULL==m_pIStorage)
  316.         {
  317.         if (NULL==pIStorage)
  318.             return FALSE;
  319.  
  320.         /*
  321.          * Attempt to open the storage under this ID.  If there is none, then
  322.          * create it.  In either case we end up with an IStorage that we
  323.          * either save in pPage or release.
  324.          */
  325.  
  326.         GetStorageName(szTemp);
  327.         hr=pIStorage->OpenStorage(szTemp, NULL, dwMode, NULL, 0, &m_pIStorage);
  328.  
  329.         if (FAILED(hr))
  330.             hr=pIStorage->CreateStorage(szTemp, dwMode, 0, 0, &m_pIStorage);
  331.         }
  332.     else
  333.         m_pIStorage->AddRef();
  334.  
  335.     if (FAILED(hr))
  336.         return FALSE;
  337.  
  338.     m_cOpens++;
  339.     return TRUE;
  340.     }
  341.  
  342.  
  343.  
  344.  
  345. /*
  346.  * CTenant::Close
  347.  *
  348.  * Purpose:
  349.  *  Possibly commits the storage, then releases it reversing the
  350.  *  reference count from FOpen.  If the reference on the storage
  351.  *  goes to zero, the storage is forgotten.  However, the object we
  352.  *  contain is still held and as long as it's active the storage
  353.  *  remains alive.
  354.  *
  355.  * Parameters:
  356.  *  fCommit         BOOL indicating if we're to commit.
  357.  *
  358.  * Return Value:
  359.  *  None
  360.  */
  361.  
  362. void CTenant::Close(BOOL fCommit)
  363.     {
  364.     if (fCommit)
  365.         Update();
  366.  
  367.     if (NULL!=m_pIStorage)
  368.         {
  369.         m_pIStorage->Release();
  370.  
  371.         /*
  372.          * We can't use a zero reference count to know when to NULL
  373.          * this since other things might have AddRef'd the storage.
  374.          */
  375.         if (0==--m_cOpens)
  376.             m_pIStorage=NULL;
  377.         }
  378.  
  379.     return;
  380.     }
  381.  
  382.  
  383.  
  384.  
  385. /*
  386.  * CTenant::Update
  387.  *
  388.  * Purpose:
  389.  *  Forces a common on the page if it's open.
  390.  *
  391.  * Parameters:
  392.  *  None
  393.  *
  394.  * Return Value:
  395.  *  BOOL            TRUE if the object is open, FALSE otherwise.
  396.  */
  397.  
  398. BOOL CTenant::Update(void)
  399.     {
  400.     LPPERSISTSTORAGE    pIPS;
  401.  
  402.     if (NULL!=m_pIStorage)
  403.         {
  404.         /*
  405.          * We need to OleSave again because we might have changed the
  406.          * size or position of this tenant.  We also need to save the
  407.          * rectangle on the page, since that's not known to OLE.
  408.          */
  409.         m_pObj->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&pIPS);
  410.         OleSave(pIPS, m_pIStorage, TRUE);
  411.         pIPS->SaveCompleted(NULL);
  412.         pIPS->Release();
  413.  
  414.         m_pIStorage->Commit(STGC_ONLYIFCURRENT);
  415.         }
  416.  
  417.     return FALSE;
  418.     }
  419.  
  420.  
  421.  
  422.  
  423.  
  424. /*
  425.  * CTenant::Destroy
  426.  *
  427.  * Purpose:
  428.  *  Removes this page from the given storage.  The caller should
  429.  *  eventually delete this CTenant object to free the object herein.
  430.  *  Nothing is committed when being destroyed.
  431.  *
  432.  * Parameters:
  433.  *  pIStorage       LPSTORAGE contianing this page on which to call
  434.  *                  ::DestroyElement
  435.  *
  436.  * Return Value:
  437.  *  None
  438.  */
  439.  
  440. void CTenant::Destroy(LPSTORAGE pIStorage)
  441.     {
  442.     char        szTemp[32];
  443.  
  444.     if (NULL!=pIStorage)
  445.         {
  446.         if (NULL!=m_pIStorage)
  447.             {
  448.             //Remove all reference/open counts on this storage.
  449.             while (0!=m_cOpens)
  450.                 {
  451.                 m_pIStorage->Release();
  452.                 m_cOpens--;
  453.                 }
  454.             }
  455.  
  456.         GetStorageName(szTemp);
  457.         pIStorage->DestroyElement(szTemp);
  458.  
  459.         m_pIStorage=NULL;
  460.         }
  461.  
  462.     //m_pObj is released in destructor.
  463.     return;
  464.     }
  465.  
  466.  
  467.  
  468.  
  469. /*
  470.  * CTenant::Select
  471.  *
  472.  * Purpose:
  473.  *  Selects or deselects the tenant.
  474.  *
  475.  * Parameters:
  476.  *  fSelect         BOOL indicating the new state of the tenant.
  477.  *
  478.  * Return Value:
  479.  *  None
  480.  */
  481.  
  482. void CTenant::Select(BOOL fSelect)
  483.     {
  484.     BOOL        fWasSelected;
  485.     DWORD       dwState;
  486.     RECT        rc;
  487.     HDC         hDC;
  488.  
  489.     fWasSelected=(BOOL)(TENANTSTATE_SELECTED & m_dwState);
  490.  
  491.     //Nothing to do when there's no change.
  492.     if (fWasSelected==fSelect)
  493.         return;
  494.  
  495.     dwState=m_dwState & ~TENANTSTATE_SELECTED;
  496.     m_dwState=dwState | ((fSelect) ? TENANTSTATE_SELECTED : 0);
  497.  
  498.     /*
  499.      * Draw sizing handles to show the selection state.  We convert
  500.      * things to MM_TEXT since that's what this function expects.
  501.      */
  502.  
  503.     RECTFROMRECTL(rc, m_rcl);
  504.     RectConvertMappings(&rc, NULL, TRUE);
  505.     OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
  506.  
  507.     hDC=GetDC(m_hWnd);
  508.  
  509.     OleUIDrawHandles(&rc, hDC, OLEUI_HANDLES_INSIDE | OLEUI_HANDLES_NOBORDER
  510.         | OLEUI_HANDLES_USEINVERSE, CXYHANDLE, !fWasSelected);
  511.  
  512.     ReleaseDC(m_hWnd, hDC);
  513.     return;
  514.     }
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522. /*
  523.  * CTenant::Activate
  524.  *
  525.  * Purpose:
  526.  *  Activates a verb on the object living in the tenant.  Does nothing
  527.  *  for static objects.
  528.  *
  529.  * Parameters:
  530.  *  iVerb           DWORD of the verb to execute.
  531.  *
  532.  * Return Value:
  533.  *  BOOL            TRUE if the object changed due to this verb execution.
  534.  */
  535.  
  536. BOOL CTenant::Activate(DWORD iVerb)
  537.     {
  538.     MessageBeep(0); //Nothing doing for now.
  539.     return FALSE;
  540.     }
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547. /*
  548.  * CTenant::Draw
  549.  *
  550.  * Purpose:
  551.  *  Draws the tenant in its rectangle on the given hDC.  We assume the
  552.  *  DC is already set up for the mapping mode in which our rectangle
  553.  *  is expressed, since the Page we're in tells us both the rect and
  554.  *  the hDC.
  555.  *
  556.  * Parameters:
  557.  *  hDC             HDC in which to draw.  Could be a metafile, memory
  558.  *                  DC, screen, or printer.  We simply don't know.
  559.  *  ptd             DVTARGETDEVICE FAR * describing the device.
  560.  *  hIC             HDC holding an information context (printing).
  561.  *  xOff, yOff      int offsets for the page in lometric
  562.  *  fNoColor        BOOL indicating if we should do B & W
  563.  *  fPrinter        BOOL indicating if we should render for a printer.
  564.  *
  565.  * Return Value:
  566.  *  None
  567.  */
  568.  
  569. void CTenant::Draw(HDC hDC, DVTARGETDEVICE FAR *ptd, HDC hIC, int xOff
  570.     , int yOff, BOOL fNoColor, BOOL fPrinter)
  571.     {
  572.     HRESULT         hr;
  573.     RECT            rc;
  574.     RECTL           rcl;
  575.     UINT            uMM;
  576.     LPVIEWOBJECT    pIViewObject;
  577.  
  578.     hr=m_pObj->QueryInterface(IID_IViewObject, (LPVOID FAR *)&pIViewObject);
  579.  
  580.     if (FAILED(hr))
  581.         return;
  582.  
  583.     RECTFROMRECTL(rc, m_rcl);
  584.     OffsetRect(&rc, -xOff, -yOff);
  585.     RECTLFROMRECT(rcl, rc);
  586.  
  587.     //We have to use Draw since we have a target device and IC.
  588.     hr=pIViewObject->Draw(m_fe.dwAspect, -1, NULL, ptd, hIC, hDC
  589.         , &rcl, NULL, NULL, 0);
  590.     pIViewObject->Release();
  591.  
  592.     /*
  593.      * If Draw failed, then perhaps it couldn't work for the device,
  594.      * so try good old OleDraw as a last resort.  The code will
  595.      * generally be OLE_E_BLANK.
  596.      */
  597.     if (FAILED(hr))
  598.         OleDraw(m_pObj, m_fe.dwAspect, hDC, &rc);
  599.  
  600.     if (!fPrinter && TENANTSTATE_SELECTED & m_dwState)
  601.         {
  602.         /*
  603.          * Draw sizing handles to show the selection state.  We convert
  604.          * things to MM_TEXT since that's what this function expects.
  605.          */
  606.         RectConvertMappings(&rc, NULL, TRUE);
  607.         uMM=SetMapMode(hDC, MM_TEXT);
  608.  
  609.         OleUIDrawHandles(&rc, hDC, OLEUI_HANDLES_INSIDE | OLEUI_HANDLES_NOBORDER
  610.             | OLEUI_HANDLES_USEINVERSE, CXYHANDLE, TRUE);
  611.  
  612.         uMM=SetMapMode(hDC, uMM);
  613.         }
  614.  
  615.     return;
  616.     }
  617.  
  618.  
  619.  
  620.  
  621.  
  622. /*
  623.  * CTenant::Repaint
  624.  * CTenant::Invalidate
  625.  *
  626.  * Purpose:
  627.  *  Repaints the tenant where it lies or invalidates its area
  628.  *  for later repainting.
  629.  *
  630.  * Parameters:
  631.  *  None
  632.  *
  633.  * Return Value:
  634.  *  None
  635.  */
  636.  
  637. void CTenant::Repaint(void)
  638.     {
  639.     RECT        rc;
  640.     HDC         hDC;
  641.  
  642.     hDC=GetDC(m_hWnd);
  643.     SetRect(&rc, m_pPG->m_xPos, m_pPG->m_yPos, 0, 0);
  644.     RectConvertMappings(&rc, NULL, FALSE);
  645.  
  646.     SetMapMode(hDC, MM_LOMETRIC);
  647.     Draw(hDC, NULL, NULL, rc.left, rc.top, FALSE, FALSE);
  648.  
  649.     ReleaseDC(m_hWnd, hDC);
  650.     return;
  651.     }
  652.  
  653.  
  654. void CTenant::Invalidate(void)
  655.     {
  656.     RECTL       rcl;
  657.     RECT        rc;
  658.  
  659.     RectGet(&rcl, TRUE);
  660.     RECTFROMRECTL(rc, rcl);
  661.  
  662.     OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
  663.     InvalidateRect(m_hWnd, &rc, FALSE);
  664.  
  665.     return;
  666.     }
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673. /*
  674.  * CTenant::ObjectGet
  675.  *
  676.  * Purpose:
  677.  *  Retrieves the LPUNKNOWN of the object in use by this tenant
  678.  *
  679.  * Parameters:
  680.  *  ppUnk           LPUNKNOWN FAR * in which to return the object pointer.
  681.  *
  682.  * Return Value:
  683.  *  None
  684.  */
  685.  
  686. void CTenant::ObjectGet(LPUNKNOWN FAR *ppUnk)
  687.     {
  688.     if (NULL!=ppUnk)
  689.         {
  690.         *ppUnk=m_pObj;
  691.         m_pObj->AddRef();
  692.         }
  693.  
  694.     return;
  695.     }
  696.  
  697.  
  698.  
  699.  
  700.  
  701. /*
  702.  * CTenant::FormatEtcGet
  703.  *
  704.  * Purpose:
  705.  *  Retrieves the FORMATETC in use by this tenant
  706.  *
  707.  * Parameters:
  708.  *  pFE             LPFORMATETC in which to store the information.
  709.  *  fPresentation   BOOL indicating if we want the real format or that
  710.  *                  of the presentation.
  711.  *
  712.  * Return Value:
  713.  *  None
  714.  */
  715.  
  716. void CTenant::FormatEtcGet(LPFORMATETC pFE, BOOL fPresentation)
  717.     {
  718.     if (NULL!=pFE)
  719.         *pFE=m_fe;
  720.  
  721.     return;
  722.     }
  723.  
  724.  
  725.  
  726.  
  727.  
  728. /*
  729.  * CTenant::SizeGet
  730.  * CTenant::SizeSet
  731.  * CTenant::RectGet
  732.  * CTenant::RectSet
  733.  *
  734.  * Purpose:
  735.  *  Returns or sets the size/position of the object contained here.
  736.  *
  737.  * Parameters:
  738.  *  pszl/prcl       LPSIZEL (Size) or LPRECTL (Rect) with the extents of
  739.  *                  interest.  In Get situations, this will receive the
  740.  *                  extents; in Set it contains the extents.
  741.  *  fDevice         BOOL indicating that pszl/prcl is expressed in device
  742.  *                  units.  Otherwise it's LOMETRIC.
  743.  *
  744.  * Return Value:
  745.  *  None
  746.  */
  747.  
  748. void CTenant::SizeGet(LPSIZEL pszl, BOOL fDevice)
  749.     {
  750.     if (!fDevice)
  751.         {
  752.         pszl->cx=m_rcl.right-m_rcl.left;
  753.         pszl->cy=m_rcl.bottom-m_rcl.top;
  754.         }
  755.     else
  756.         {
  757.         RECT        rc;
  758.  
  759.         SetRect(&rc, (int)(m_rcl.right-m_rcl.left)
  760.             , (int)(m_rcl.bottom-m_rcl.top), 0, 0);
  761.  
  762.         RectConvertMappings(&rc, NULL, TRUE);
  763.  
  764.         pszl->cx=(long)rc.left;
  765.         pszl->cy=(long)rc.top;
  766.         }
  767.  
  768.     return;
  769.     }
  770.  
  771.  
  772. void CTenant::SizeSet(LPSIZEL pszl, BOOL fDevice)
  773.     {
  774.     SIZEL           szl;
  775.  
  776.     if (!fDevice)
  777.         {
  778.         szl=*pszl;
  779.         m_rcl.right =pszl->cx+m_rcl.left;
  780.         m_rcl.bottom=pszl->cy+m_rcl.top;
  781.         }
  782.     else
  783.         {
  784.         RECT        rc;
  785.  
  786.         SetRect(&rc, (int)pszl->cx, (int)pszl->cy, 0, 0);
  787.         RectConvertMappings(&rc, NULL, FALSE);
  788.  
  789.         m_rcl.right =(long)rc.left+m_rcl.left;
  790.         m_rcl.bottom=(long)rc.top+m_rcl.top;
  791.  
  792.         SETSIZEL(szl, (long)rc.left, (long)rc.top);
  793.         }
  794.  
  795.  
  796.     //Tell OLE that this object was resized.
  797.     if (NULL!=m_pObj)
  798.         {
  799.         HRESULT     hr;
  800.         LPOLEOBJECT pIOleObject;
  801.  
  802.         hr=m_pObj->QueryInterface(IID_IOleObject, (LPVOID FAR *)&pIOleObject);
  803.  
  804.         if (SUCCEEDED(hr))
  805.             {
  806.             //Convert our LOMETRIC into HIMETRIC by *=10
  807.             szl.cx*=10;
  808.             szl.cy*=-10;    //Our size is stored negative.
  809.  
  810.             pIOleObject->SetExtent(m_fe.dwAspect, &szl);
  811.             pIOleObject->Release();
  812.             }
  813.         }
  814.  
  815.     return;
  816.     }
  817.  
  818.  
  819. void CTenant::RectGet(LPRECTL prcl, BOOL fDevice)
  820.     {
  821.     if (!fDevice)
  822.         *prcl=m_rcl;
  823.     else
  824.         {
  825.         RECT        rc;
  826.  
  827.         RECTFROMRECTL(rc, m_rcl);
  828.         RectConvertMappings(&rc, NULL, TRUE);
  829.         RECTLFROMRECT(*prcl, rc);
  830.         }
  831.  
  832.     return;
  833.     }
  834.  
  835.  
  836. void CTenant::RectSet(LPRECTL prcl, BOOL fDevice)
  837.     {
  838.     SIZEL   szl;
  839.  
  840.     if (!fDevice)
  841.         m_rcl=*prcl;
  842.     else
  843.         {
  844.         RECT        rc;
  845.  
  846.         RECTFROMRECTL(rc, *prcl);
  847.         RectConvertMappings(&rc, NULL, FALSE);
  848.         RECTLFROMRECT(m_rcl, rc);
  849.         }
  850.  
  851.     //Tell ourselves that the size changes.
  852.     SETSIZEL(szl, m_rcl.right-m_rcl.left, m_rcl.bottom-m_rcl.top);
  853.     SizeSet(&szl, FALSE);
  854.  
  855.     return;
  856.     }
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864. /*
  865.  * CTenant::CreateStatic
  866.  * (Protected)
  867.  *
  868.  * Purpose:
  869.  *  Creates a new static bitmap or metafile object for this tenant
  870.  *  using a freeloading method allowing us to specify exactly which
  871.  *  type of data we want to paste since OleCreateStaticFromData doesn't.
  872.  *
  873.  * Parameters:
  874.  *  pIDataObject    LPDATAOBJECT from which to paste.
  875.  *  pFE             LPFORMATETC describing the format to paste.
  876.  *  ppObj           LPUNKNOWN FAR * into which we store the object pointer.
  877.  *
  878.  * Return Value:
  879.  *  HRESULT         NOERROR on success, error code otherwise.
  880.  */
  881.  
  882. HRESULT CTenant::CreateStatic(LPDATAOBJECT pIDataObject, LPFORMATETC pFE
  883.     , LPUNKNOWN FAR * ppObj)
  884.     {
  885.     HRESULT             hr;
  886.     STGMEDIUM           stm;
  887.     LPUNKNOWN           pIUnknown;
  888.     LPOLECACHE          pIOleCache;
  889.     LPPERSISTSTORAGE    pIPersistStorage;
  890.     CLSID               clsID;
  891.  
  892.     *ppObj=NULL;
  893.  
  894.     //Try to get the data desired as specified in pFE->cfFormat
  895.     hr=pIDataObject->GetData(pFE, &stm);
  896.  
  897.     if (FAILED(hr))
  898.         return hr;
  899.  
  900.     //Create the object to handle this data.
  901.     if (CF_METAFILEPICT==pFE->cfFormat)
  902.         clsID=CLSID_FreeMetafile;
  903.     else
  904.         clsID=CLSID_FreeDib;
  905.  
  906.     hr=OleCreateDefaultHandler(clsID, NULL, IID_IUnknown
  907.         , (LPVOID FAR *)&pIUnknown);
  908.  
  909.     if (FAILED(hr))
  910.         {
  911.         ReleaseStgMedium(&stm);
  912.         return hr;
  913.         }
  914.  
  915.     //Stuff the data into the object
  916.     pIUnknown->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&pIPersistStorage);
  917.     pIPersistStorage->InitNew(m_pIStorage);
  918.  
  919.     //Now that we have the cache object, shove the data into it.
  920.     pIUnknown->QueryInterface(IID_IOleCache, (LPVOID FAR *)&pIOleCache);
  921.     pIOleCache->Cache(pFE, ADVF_PRIMEFIRST, NULL);
  922.  
  923.     hr=pIOleCache->SetData(pFE, &stm, TRUE);
  924.     pIOleCache->Release();
  925.  
  926.     //Insure there is a persistent copy on the disk; OleSave does it all for us
  927.     OleSave(pIPersistStorage, m_pIStorage, TRUE);
  928.     pIPersistStorage->Release();
  929.  
  930.     //The cache owns this now.
  931.     ReleaseStgMedium(&stm);
  932.  
  933.     if (FAILED(hr))
  934.         pIUnknown->Release();
  935.     else
  936.         *ppObj=pIUnknown;
  937.  
  938.     return hr;
  939.     }
  940.